{% set prefix = DEFAULT_CONTAINER_REGISTRY %}
{% if CONFIGURED_ARCH == "armhf" and MULTIARCH_QEMU_ENVIRON == "y" %}
FROM {{ prefix }}multiarch/debian-debootstrap:armhf-stretch
{% elif CONFIGURED_ARCH == "arm64" and MULTIARCH_QEMU_ENVIRON == "y" %}
FROM {{ prefix }}multiarch/debian-debootstrap:arm64-stretch
{% elif PTF_ENV_PY_VER == "mixed" %}
FROM {{ prefix}}debian:buster
{% else %}
FROM {{ prefix }}debian:bookworm
{% endif %}

{% from "dockers/dockerfile-macros.j2" import install_python_wheels, copy_files, install_offending_packages %}

USER root
WORKDIR /root

LABEL maintainer="Pavel Shirshov"

COPY ["sources.list.{{ CONFIGURED_ARCH }}", "/etc/apt/sources.list"]
COPY ["no-check-valid-until", "/etc/apt/apt.conf.d"]
COPY ["apt-retries-count", "/etc/apt/apt.conf.d"]

## Make apt-get non-interactive
ENV DEBIAN_FRONTEND=noninteractive

## Set the apt source, update package cache and install necessary packages
## TODO: Clean up this step
RUN apt-get update          \
    && apt-get upgrade -y   \
    && apt-get dist-upgrade -y  \
    && apt-get install -y   \
        autoconf            \
        openssh-server      \
        vim                 \
        telnet              \
        net-tools           \
        traceroute          \
        lsof                \
        tcpdump             \
        ethtool             \
        unzip               \
        pkg-config          \
        binutils            \
        build-essential     \
        libssl-dev          \
        libffi-dev          \
        wget                \
        cmake               \
        libqt5core5a        \
        libqt5network5      \
{% if PTF_ENV_PY_VER == "mixed" %}
        libboost-atomic1.71.0 \
{% else %}
        libboost-atomic1.74.0 \
        flex                  \
        bison                 \
        tcpd                  \
        libwrap0              \
        libwrap0-dev          \
        libthrift-dev         \
        python3-thrift        \
{% endif %}
        less                \
        git                 \
        iputils-ping        \
        hping3              \
        curl                \
        tmux                \
{% if PTF_ENV_PY_VER == "mixed" %}
        python              \
        python-dev          \
        python-libpcap      \
        python-scapy        \
        python-six          \
{% endif %}
        python3             \
        python3-venv        \
        python3-pip         \
        python3-dev         \
        python3-scapy       \
        python3-six         \
        python3-gi          \
        libpcap-dev         \
{% if PTF_ENV_PY_VER == "mixed" %}
        tacacs+             \
{% endif %}
        rsyslog             \
        ntp                 \
        ntpstat             \
        ntpdate             \
        arping              \
        bridge-utils        \
        libteam-utils       \
        gdb                 \
        automake            \
        iproute2            \
        iptables            \
        wireshark-common    \
        freeradius          \
        quilt

{% if PTF_ENV_PY_VER == "py3" %}
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1 \
    && update-alternatives --install /usr/bin/pip pip /usr/bin/pip3 1 \
    && update-alternatives --install /usr/bin/pdb pdb /usr/bin/pdb3 1 \
    && update-alternatives --install /usr/bin/pydoc pydoc /usr/bin/pydoc3 1 \
    && update-alternatives --install /usr/bin/pygettext pygettext /usr/bin/pygettext3 1
{% endif %}

COPY openbfdd-patches/ /root/openbfdd-patches/
# Install all python modules from pypi. python-scapy is exception, ptf debian package requires python-scapy
# TODO: Clean up this step
RUN rm -rf /debs \
    && apt-get -y autoclean \
    && apt-get -y autoremove \
    && rm -rf /var/lib/apt/lists/* \
{% if PTF_ENV_PY_VER == "mixed" %}
    && wget --https-only https://bootstrap.pypa.io/pip/2.7/get-pip.py \
    && python get-pip.py \
    && rm -f get-pip.py \
    && pip install setuptools \
    && pip install supervisor \
    && pip install ipython==5.4.1 \
    && git clone https://github.com/p4lang/scapy-vxlan.git \
    && cd scapy-vxlan \
    && python setup.py install \
    && cd .. \
    && rm -fr scapy-vxlan \
{% endif %}
    && git clone https://github.com/sflow/sflowtool \
    && cd sflowtool \
    && git checkout v6.04 \
    && ./boot.sh \
    && ./configure \
    && make \
    && make install \
    && cd  .. \
    && rm -fr sflowtool \
    && git clone https://github.com/dyninc/OpenBFDD.git \
    && cd OpenBFDD \
    && git apply /root/openbfdd-patches/broken-build-bookworm.patch \
    && ./autogen.sh \
    && ./configure \
    && make \
    && make install \
    && cd  .. \
    && rm -fr OpenBFDD \
    && wget https://github.com/nanomsg/nanomsg/archive/1.0.0.tar.gz \
    && tar xvfz 1.0.0.tar.gz \
    && cd nanomsg-1.0.0    \
    && mkdir -p build      \
    && cd build            \
    && cmake ..            \
    && make install        \
    && ldconfig            \
    && cd ../..            \
    && rm -fr nanomsg-1.0.0 \
    && rm -f 1.0.0.tar.gz  \
{% if PTF_ENV_PY_VER == "mixed" %}
    && pip install cffi    \
    && pip install nnpy    \
    && pip install dpkt    \
    && pip install ipaddress \
    && pip install pysubnettree \
    && pip install paramiko \
    && pip install flask   \
    && pip install tornado \
    && pip install exabgp==3.4.17\
    && pip install pyaml   \
    && pip install pybrctl pyro4 rpyc yabgp \
    && pip install unittest-xml-reporting \
    && pip install pyrasite \
    && pip install retrying \
{% endif %}
    && mkdir -p /opt       \
    && cd /opt             \
    && wget https://raw.githubusercontent.com/p4lang/ptf/master/ptf_nn/ptf_nn_agent.py

{% if PTF_ENV_PY_VER == "py3" %}
RUN git clone https://github.com/facebook/tac_plus \
    && cd tac_plus \
    && cd tacacs-F4.0.4.28 \
    && ./configure LDFLAGS="-Wl,-rpath=/usr/local/lib" \
    && make install \
    && ln -s /usr/local/sbin/tac_plus /usr/sbin/tac_plus \
    && ln -s /usr/local/bin/tac_pwd /usr/sbin/tac_pwd \
    && mkdir /etc/tacacs+ \
    && chmod 0755 /etc/tacacs+
COPY ["tacacs_plus", "/etc/init.d"]
COPY ["tacacs+", "/etc/default"]
{% endif %}

# Workaround: Tornado installed outside of the
# virtualenv as the call to the process API
# Ansible -> Supervisor -> ExaBGP -> Process API
# causes the process API to have a restricted 
# environment without access to the virtualenv.
{% if PTF_ENV_PY_VER == "py3" %}
    RUN pip3 install --break-system-packages tornado
{% endif %}


RUN python3 -m venv --system-site-packages env-python3
# Activating a virtualenv. The virtualenv automatically works for RUN, ENV and CMD.
ENV VIRTUAL_ENV=/root/env-python3
ARG BACKUP_OF_PATH="$PATH"
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 PYTHONIOENCODING=UTF-8

{% if PTF_ENV_PY_VER == "mixed" %}
RUN python3 -m pip install --upgrade --ignore-installed pip
{% endif %}

# For py3 image the following offending packages below do not use the updated 
# setuptools on Python 3.9. The packages downgrade setuptools 
# to 40.x causing further installations to fail
{% if PTF_ENV_PY_VER == "py3" %}
{% set offending_packages = ["supervisor", "ipython==5.4.1", "exabgp==4.2.25", "grpcio-tools", "pybrctl", "pyrasite", "scapy==2.5.0", "thrift"] %}
{{ install_offending_packages(offending_packages) }}
{% else %}
RUN pip3 install setuptools \
        && pip3 install supervisor \
        && pip3 install ipython==5.4.1 \
        && pip3 install exabgp==4.2.25 \
        && pip3 install grpcio-tools \
        && pip3 install pybrctl \
        && pip3 install pyrasite \
        && pip3 install scapy==2.5.0 \
        && pip3 install thrift
{% endif %}

# Install all python modules from pypi. python3-scapy is exception, 
# ptf debian package requires python3-scapy
{% if PTF_ENV_PY_VER == "py3" %}
# Werkzeug 3.1.3 has a bug and causes announce routes to fail
# by returning 413 Request Entity Too Large though request buffers
# have been increased.
RUN pip3 install Flask==3.0.3   \
    && pip3 install Werkzeug==3.1.2 \
{% else %}
RUN pip3 install Flask \
{% endif %}
    && pip3 install Cython \
    && pip3 install cffi    \
    && pip3 install nnpy    \
    && pip3 install dpkt    \
    && pip3 install ipaddress \
    && pip3 install pysubnettree \
    && pip3 install paramiko \
    && pip3 install tornado \
    && pip3 install Flask   \
    && pip3 install exabgp \
    && pip3 install pyaml   \
    && pip3 install pyro4 rpyc \
    && pip3 install unittest-xml-reporting \
    && pip3 install python-libpcap \
    && pip3 install enum34 \
    && pip3 install grpcio \
    && pip3 install six==1.16.0 \
    && pip3 install itsdangerous \
    && pip3 install retrying \
    && pip3 install jinja2

# gnxi/gnmi_cli_py requires protobuf 3.20.x or lower
# Bookworm by default use 5.29.x. Resetting it to 3.20.3
# to avoid issues with gnmi tests.
RUN set -e; \
    . /etc/os-release; \
    if [ "$VERSION_CODENAME" = "bookworm" ]; then \
        pip install protobuf==3.20.3; \
    else \
        pip install protobuf; \
    fi

{% if docker_ptf_whls.strip() -%}
# Copy locally-built Python wheel dependencies
{{ copy_files("python-wheels/", docker_ptf_whls.split(' '), "/python-wheels/") }}

# Install locally-built Python wheel dependencies
{{ install_python_wheels(docker_ptf_whls.split(' ')) }}
{% endif %}

## Adjust sshd settings
RUN mkdir /var/run/sshd \
    && echo 'root:root' | chpasswd \
    && sed -ri '/^#?PermitRootLogin/c\PermitRootLogin yes' /etc/ssh/sshd_config \
    && sed -ri '/^#?UsePAM/c\UsePAM no' /etc/ssh/sshd_config \
    && sed -ri '/^#?UseDNS/c\UseDNS no' /etc/ssh/sshd_config

COPY supervisord.conf /etc/supervisor/
COPY conf.d/ /etc/supervisor/conf.d/
COPY ptf_tgen.sh /ptf_tgen/

{% if PTF_ENV_PY_VER == "mixed" %}
# Move tcpdump into /usr/bin Otherwise it's impossible to run tcpdump due to a docker bug
RUN mv /usr/sbin/tcpdump /usr/bin/tcpdump
RUN ln -s /usr/bin/tcpdump /usr/sbin/tcpdump
{% endif %}

RUN mkdir -p /var/log/supervisor

# Install Python-based GNMI client
RUN git clone https://github.com/google/gnxi.git \
    && cd gnxi \
    && git checkout 208acfa85f5b5b8717e14896e9d6ee93cfda9d5f

COPY gnxi-patches/ gnxi/patches/


{% if PTF_ENV_PY_VER == "mixed" %}
RUN cd gnxi \
    && quilt push -a \
    && cd gnmi_cli_py \
    && pip install -r requirements.txt
{% else %}
RUN cd gnxi \
    && quilt push -a
{% endif %}

# Deactivating a virtualenv.
# ENV PATH="$BACKUP_OF_PATH"

# Install gnoic tool
# Without specifying the version there is a failure
# to determine the latest version automatically.
#
# root@a2014cb5bc54:~/gnoic# ./install.sh
# Warning: Failed to verify the package: https://api.github.com/repos/karimra/gnoic/releases/latest, the version is not specified
# Could not determine the latest release
# Failed to install gnoic
# For support, go to https://github.com/karimra/gnoic/issues
RUN git clone https://github.com/karimra/gnoic.git \
    && cd gnoic \
    && git checkout 57aac3d \
    && chmod +x install.sh \
    && ./install.sh --version 0.1.0 \
    && cd .. \
    && rm -rf gnoic

COPY \
{% for deb in docker_ptf_debs.split(' ') -%}
debs/{{ deb }}{{' '}}
{%- endfor -%}
debs/

{% if PTF_ENV_PY_VER == "mixed" %}
RUN dpkg -i \
{% for deb in docker_ptf_debs.split(' ') -%}
debs/{{ deb }}{{' '}}
{%- endfor %}
{% else %}
RUN dpkg -i debs/python-saithrift_0.9.4_amd64.deb
{% endif %}

# {% if PTF_ENV_PY_VER == "py3" %}
# # Create symlink so that test scripts and ptf_runner invocation path
# # is same across python 2 and python 3 envs. Note that for virtual-env
# # ptf is under /root/env-python3/bin.
# # TODO - cleanup when the supported PTF image is py3only across all branches
# RUN mkdir -p /root/env-python3/bin \
#     && ln -s /usr/local/bin/ptf /usr/bin/ptf \
#     && ln -s /usr/bin/python /root/env-python3/bin/python3 \
#     && ln -s /usr/bin/python /root/env-python3/bin/python \
#     && ln -s /usr/local/bin/ptf /root/env-python3/bin/ptf
# {% endif %}

# There are some scripts like supervisorctl and others invoked from
# custom Ansible modules which use exec_command to run these. Since
# Ansible module's exec_command uses a restricted shell without sourcing
# the profile or other rc files the PATH does not include the virtualenv.
# This step keeps links to required binaries from /usr/local/bin to the
# virtualenv bin directory.
RUN set -eux; \
  for f in /root/env-python3/bin/*; do \
    base="$(basename "$f")"; \
    case "$base" in \
      python*|pip*) continue ;; \
    esac; \
    ln -sf "$f" "/usr/local/bin/$base"; \
  done

RUN echo "/root/env-python3/lib/python3.11/site-packages" > /usr/lib/python3/dist-packages/virtualenv.pth; \
    echo "/root/env-python3/lib/python3.11/site-packages" > /usr/lib/python3.11/dist-packages/virtualenv.pth

RUN echo "PYTHONPATH=/root/env-python3/lib/python3.11/site-packages" >> /etc/environment

COPY ["*.ini", "/etc/ptf/"]
EXPOSE 22 8009

ENTRYPOINT ["/root/env-python3/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"]
